/**
 * @Description: 封装Unicode加解密方式
 * @Version: 1.0
 * @Author: 琴时
 * @Date: 2021-11-28 23:22:41
 * @LastEditors: 琴时
 * @LastEditTime: 2021-12-11 16:12:42
 */

/* 封装Unicode加密方式 */
export const toCode = (params) => {
    params = params.toString(); //避免参数不是字符串
    /* 定义密钥 */
    const number = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];//数字部分秘钥
    const lower = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];//小写字母部分秘钥
    const capital = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];//大写字母部分秘钥
    const keyList = [...number, ...lower, ...capital];//构建秘钥数组
    const len = keyList.length;//秘钥长度
    /* end */
    /**
     * 定义临时变量
     * unicodeValue:最终加密值
     */
    let unicodeValue = "", b, b1, b2, b3;
    /* 遍历待加密字符串 */
    for (let i = 0; i < params.length; i++) {
        b = params.charCodeAt(i); //逐个提取每个字符，并获取Unicode编码值
        b1 = b % len; //第一轮求余数
        b = (b - b1) / len; //求最大倍数
        b2 = b % len; //第二轮求余数
        b = (b - b2) / len; //求最大倍数
        b3 = b % len; //第三轮求余数
        unicodeValue += keyList[b3] + keyList[b2] + keyList[b1]; //根据余数值映射到密钥中对应下标位置的字符
    }
    return unicodeValue; //返回这些映射的字符(加密后)
};

/* 封装Unicode解密方式 */
export const fromCode = (params) => {
    params = params.toString(); //避免参数不是字符串
    /* 定义密钥 */
    const number = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"];//数字部分秘钥
    const lower = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];//小写字母部分秘钥
    const capital = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];//大写字母部分秘钥
    const keyList = [...number, ...lower, ...capital];//构建秘钥数组
    const len = keyList.length;//秘钥长度
    let result = "",
        b = 0,
        b1,
        b2,
        b3,
        arr; //定义临时变量
    //计算加密字符串包含的字符数，创建一个x位的数组
    let x = Math.ceil(params.length / 3);
    arr = new Array(x);
    for (let i = 0; i < arr.length; i++) {
        //以数组的长度循环次数，遍历加密字符串
        b1 = keyList.indexOf(params.charAt(b)); //截取周期内第d个字符串，计算在密钥中的索引值
        b++;
        b2 = keyList.indexOf(params.charAt(b)); //截取周期内第d个字符串，计算在密钥中的索引值
        b++;
        b3 = keyList.indexOf(params.charAt(b)); //截取周期内第d个字符串，计算在密钥中的索引值
        b++;
        arr[i] = b1 * len * len + b2 * len + b3; //利用索引值，反推被加密字符的Unicode编码值
    }
    // 将数组转换成字符串连接起来
    let str1 = arr.join(",");
    //用fromCharCode()算出字符串
    result = eval("String.fromCharCode(" + str1 + ")");
    return result; //返回被解密的字符串
};

/******* 
 * @description: 校验数据是否一致
 * @author: 琴时
 * @param {params1} [未加密]
 * @param {params2} [已加密]
 * @return {boolean} 返回校验结果<布尔值>
 */
export const checkCode = (params1,params2) => {
    return params1===fromCode(params2); //返回校验结果<布尔值>
};

/**
 * 测试用例
 * 将src/index.js底部执行函数:selectTest(params)的实参params改为2
 * 直接无法测试，请使用npm run dev或者去掉 export 使用node运行当前界面测试即可
 */

console.log('测试数据加解密-加密:', toCode('123456'))//00N00O00P00Q00R00S
console.log('测试数据加解密-解密:', fromCode(toCode('123456')))//123456
console.log('测试数据加解密-校验:', checkCode('123456',toCode('123456')))//123456